iT邦幫忙

2022 iThome 鐵人賽

DAY 29
0
自我挑戰組

菜鳥前端修練之旅系列 第 29

Day 29 | 【Vue】Suspense

  • 分享至 

  • xImage
  •  

在處理 API 或其他非同步事件時,常常需要另外定義其他狀態:例如判斷是否已拿到資料等。

在 Vue3 中 我們可以使用 Suspense 輕鬆完成這件事情。

基本用法

首先新增 <Suspense>,並新增 #default 和 #fallback 兩個插槽,兩者分別代表:

  • #default:顯示「非同步處理完後」的畫面。
  • #fallback :顯示「非同步處理完前」的畫面。

簡易的程式碼如下:

<script setup>
import Dashboard from "./components/Dashboard.vue";
</script>

<template>
  <Suspense>
    <template #default>
      <Dashboard :time="2000" />
    </template>

    <template #fallback> 
      Loading... 
    </template>
  </Suspense>
</template>

Dashboard 組件的程式碼如下,我們建立了一個 Promise,中間再包一個計時器,來模擬非同步行為,計時器的秒數從父層中傳遞進來:

<script setup>
const { time } = defineProps({
  time: { type: Number },
});

const promise = (time) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, time);
  });
};

await promise(time);
</script>

<template>
  <img src="https://seeklogo.com/images/V/vite-logo-BFD4283991-seeklogo.com.png" />
</template>

上面的範例中,2 秒後 Promiseresolve(),接著會看到一張圖:

(補充:這邊因為我有用 transition,所以有漸變的動畫)

script setup

如果在組件中使用的是 script setup,那 script 中就會變成非同步行為,即在外層加了一個 async,因此我們可以在內部使用 await

反之如果是另一種寫法,外層要加上 async:

export default {
  async setup() {
    const res = await fetch(...)
    const posts = await res.json()
    return {
      posts
    }
  }
}

這個非同步行為會返回 Promise,接著如果被 resolve() 後則顯示 #default 的內容。

錯誤處理

如果過程中發生錯誤,我們可以使用生命週期的 onErrorCaptured 來捕捉,這個生命週期與 Suspense 兩者是獨立的。

<script setup>
import Dashboard from "./components/Dashboard.vue";
import { onErrorCaptured } from "vue";

onErrorCaptured((err) => {
  console.log(err)
})
</script>

多個組件

我們可能會有 #default 中放入多個組件的需求:

<template>
  <Transition>
    <Suspense>
      <template #default>
        <div>
          <Dashboard :time="2000" />
          <Dashboard :time="5000" />
        </div>
      </template>

      <template #fallback> Loading... </template>
    </Suspense>
  </Transition>
</template>

這邊會等到所有組件都完成後才會顯示,以上面這個例子是 5 秒。

PS. 如果有多個組件記得加一個根標籤在外部,否則會收到 [Vue warn]: <Suspense> slots expect a single root node. 的錯誤訊息。

如果有需求的話,也可以配合 <KeepAlive><Transition> 等其他組件一起使用。


Suspense 幫助我們更方便的管理非同步中的狀態,不過這個功能目前還在實驗階段,對這方面有疑慮的話,可能要考慮是否用在自己的專案上。

參考資料


上一篇
Day 28 | 【Vue】Provide & Inject
下一篇
Day 30 | 完賽心得
系列文
菜鳥前端修練之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言